package cn.ac.radi.userver.waste.model;

import cn.ac.radi.userver.waste.util.ProcessUtil;
import cn.ac.radi.userver.waste.util.TailingPredictCommandBuilder;
import org.slf4j.Logger;
import org.springframework.core.env.Environment;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.UUID;
import java.util.regex.Pattern;

public class TailingPredictModel {

    private Environment env = null;
    private Logger logger = null;

    private String rasterName = "";
    private String jsonName = "";
    private String inputPath = "";
    private String outputPath = "";
    private String webOutputPath = "";


    private static String PARAM_INPUT =  "userver.model.4_4.tailing_predict.input";

    public TailingPredictModel(Environment env, Logger logger){
        this.env = env;
        this.logger = logger;
    }

    public boolean run(String rasterName){

        this.rasterName = rasterName;

        String pyEnvPath = this.getPythonEnvPath();
        String pyExePath = this.getPythonPath();
        String pyCodeName = this.getPythonCodeName();
        String pyCodeHome = this.getPythonCodeHome();
        this.inputPath = this.makeInputRasterPath(rasterName);
        this.outputPath = this.getOutputPath();
        this.jsonName = this.makeJsonName();
        this.webOutputPath = this.makeOutputJsonWebPath();

        TailingPredictCommandBuilder builder = new TailingPredictCommandBuilder();
        String pyCmd = builder.buildCommand(pyExePath, pyCodeName, inputPath, outputPath, jsonName);
        logger.info(pyCmd);

        String command = "";
        if(!pyEnvPath.isEmpty()){
            //String newCmd = "cmd /C conda activate D:\\conda\\py36_torch_120 & " + command;
            String condaCmd = "cmd /C conda activate " + pyEnvPath;
            command = condaCmd + " & " + pyCmd;
        }
        else {
            command = pyCmd;
        }
        return this.runCommandProcess(command, pyCodeHome, this.logger);

        //return this.runCommandProcess(command, pyCodeHome, this.logger);

//        //String newCmd = "cmd /C mkdir H:\\temp\\a\\old";
//        //String newCmd = "cmd /C mkdir H:\\temp\\a\\old & cmd /C mkdir H:\\temp\\a\\new;";
//        //String newCmd = "cmd /C mkdir H:\\temp\\a\\old & cmd /C cd H:\\temp\\a & cmd /C H: & cmd /C mkdir new-2";
//        //String newCmd = "cmd /C mkdir H:\\new-2";
//        //String newCmd = "cmd /C cd H:\\temp\\a & cmd /C H:\\ & python app.py";
//        String newCmd = "python app.py";
//        //String newCmd = "cmd /C H:\\";
//        //String newCmd = "mkdir H:\\temp\\a\\old;mkdir H:\\temp\\a\\new;" +  command;
//        String newCmd = "cmd /C conda activate D:\\conda\\py36_torch_120 & " + command;
//        return this.runCommandProcess(newCmd, pyCodeHome, this.logger);
    }

    public String getWebOutputPath(){
        return this.webOutputPath;
    }

    public String getRasterName() {
        return rasterName;
    }

    public void setRasterName(String rasterName) {
        this.rasterName = rasterName;
    }

    private String makeInputRasterPath(){
        String inputFolder = getInputFolder();
        return Paths.get(inputFolder, this.rasterName).toString();
    }

    private String makeOutputJsonWebPath(){
        String jsonPath = Paths.get(this.outputPath, this.jsonName).toString();
        String webRoot = env.getProperty("userver.env.web_home");
        return jsonPath.replace("\\","/").replace(webRoot,"");
    }

    /**
     * 获取图像输入路径
     * @return
     */
    private String getInputFolder(){
        return env.getProperty(PARAM_INPUT);
    }

    private String makeInputRasterPath(String rasterName){
        String inputFolder = env.getProperty("userver.model.4_4.tailing_predict.input");
        return Paths.get(inputFolder, rasterName).toString();
    }

//    private String makeOutputJsonPath(){
//        String uuid = Util.generateUUID();
//        String outputPath = getOutputPath();
//        return Paths.get(outputPath, uuid+".json").toString();
//    }

    private String makeJsonName(){
        String uuid = this.generateUUID();
        return uuid+".json";
    }

    private String getOutputPath(){
        return env.getProperty("userver.model.4_4.tailing_predict.output");
    }

    private String getPythonCodeHome(){
        return env.getProperty("userver.model.4_4.tailing_predict.python_home");
    }

    private String getPythonCodeName(){
        return env.getProperty("userver.model.4_4.tailing_predict.python_name");
    }

    private String getPythonEnvPath(){
        return env.getProperty("userver.model.4_4.tailing_predict.conda_env");
    }

    public String getPythonPath(){
        return "python";
//        String pyHome = env.getProperty("userver.env.python_home");
//        return Paths.get(pyHome, "python").toString();
    }

    private String generateUUID(){
        String pattern = "[^0-9].*";
        String uuid = UUID.randomUUID().toString();
        while (!Pattern.matches(pattern,uuid)){
            uuid = UUID.randomUUID().toString();
        }
        return uuid;
    }

    public static boolean runCommandProcess(String cmd, String homePath, Logger logger){

        logger.info("\t[python命令]：" + cmd);

        long ts = System.currentTimeMillis();   //获取开始时间

        logger.debug("~~~~~~~~~开始~~~~~~~~");

        boolean ret = false;
        Process proc = null;
        try{
            Runtime rt = Runtime.getRuntime();
            proc = rt.exec(cmd, null, new File(homePath));

            ProcessUtil pu = new ProcessUtil();
            pu.writeProcessStream(proc);

            ret = true;

            proc.waitFor();
        }
        catch (IOException e){
            e.printStackTrace();
        }
        catch (RuntimeException e){
            e.printStackTrace();
        }
        catch (InterruptedException e){
            e.printStackTrace();
        }
        finally {

            logger.debug("~~~~~~~~~结束~~~~~~~~");

            long te = System.currentTimeMillis();   //获取结束时间
            logger.info("运行时间：" + Long.toString(te-ts) + " 毫秒");

            if(proc!=null){
                logger.info("~~~~~~~~销毁processor~~~~~~~~");
                proc.destroy();
            }

            return ret;
        }
    }
}
